/*
 * serdes.c
 *
 *  Created on: 2023年4月26日
 *      Author: fengke
 */
#include "../bsp.h"
#if defined(XPAR_XGPIO_I2C_0_AXI_GPIO_0_DEVICE_ID)
#if defined (SER_CFG) || defined (DES_CFG)

#if defined (DES_CFG)
struct reginfo max9296_rgb888_gmsl2[] =
{
	{0x90, 0x0313, 0x00},// CSI output disabled
//	{0x90, 0x0001, 0x12},//11=Remote control channel disabled\3Gbs,default 02=Remote control channel Enabled\6Gbs,
//	{0x90, 0x0010, 0x21},// Link A is selected, reset link
//	{0x90, 0x0010, 0xA1},// Link A is selected, reset link
	{0x90, SEQUENCE_WAIT_MS, 0x80},//delay for a while

#if 1
//	{0x90, 0x0001, 0x01},// 3Gbps mode
//	{0x90, 0x0010, 0x21},// Link A is selected, reset link
//	{0x90, SEQUENCE_WAIT_MS, 0x80},//delay for a while

	{ 0x90, 0x0002, 0x13 }, // use pipeline X
	{ 0x90, 0x0050, 0x02 }, // pipeline X stream ID
	{ 0x90, 0x0051, 0x00 }, // pipeline Y stream ID
	{ 0x90, 0x0052, 0x01 }, // pipeline Z stream ID
	{ 0x90, 0x0053, 0x03 }, // pipeline U stream ID

	{0x90, 0x0330, 0x04},
	{0x90, 0x0333, 0x4e},
	{0x90, 0x0334, 0xe4},
	{0x90, 0x040a, 0x00},
	{0x90, 0x044a, 0xd0},
	{0x90, 0x048a, 0xd0},
	{0x90, 0x04ca, 0x00},
//	{0x90, 0x031d, 0x2a},
//	{0x90, 0x0320, 0x2a},
//	{0x90, 0x0323, 0x2a},
//	{0x90, 0x0326, 0x2a},
//	{0x90, 0x031d, 0x25},
//	{0x90, 0x0320, 0x25},
//	{0x90, 0x0323, 0x25},
//	{0x90, 0x0326, 0x25},
	{0x90, 0x031d, 0x0a},
	{0x90, 0x0320, 0x0a},
	{0x90, 0x0323, 0x0a},
	{0x90, 0x0326, 0x0a},

	{0x90, 0x040b, 0x07},
	{0x90, 0x040c, 0x00},
	{0x90, 0x042d, 0x15},
	{0x90, 0x040d, 0x24},
	{0x90, 0x040e, 0x24},
	{0x90, 0x040f, 0x00},
	{0x90, 0x0410, 0x00},
	{0x90, 0x0411, 0x01},
	{0x90, 0x0412, 0x01},

//	{0x90, 0x044b, 0x07},
//	{0x90, 0x044c, 0x00},
//	{0x90, 0x046d, 0x15},
//	{0x90, 0x044d, 0x24},
//	{0x90, 0x044e, 0x24},
//	{0x90, 0x044f, 0x00},
//	{0x90, 0x0490, 0x00},
//	{0x90, 0x0451, 0x01},
//	{0x90, 0x0452, 0x01},
//
//	{0x90, 0x048b, 0x07},
//	{0x90, 0x048c, 0x00},
//	{0x90, 0x04ad, 0x15},
//	{0x90, 0x048d, 0x24},
//	{0x90, 0x048e, 0x24},
//	{0x90, 0x048f, 0x00},
//	{0x90, 0x0490, 0x00},
//	{0x90, 0x0491, 0x01},
//	{0x90, 0x0492, 0x01},
//
//	{0x90, 0x04cb, 0x07},
//	{0x90, 0x04cc, 0x00},
//	{0x90, 0x04ed, 0x15},
//	{0x90, 0x04cd, 0x24},
//	{0x90, 0x04ce, 0x24},
//	{0x90, 0x04cf, 0x00},
//	{0x90, 0x04D0, 0x00},
//	{0x90, 0x04D1, 0x01},
//	{0x90, 0x04D2, 0x01},

	{0x90, 0x0332, 0xF0},
	{0x90, 0x0313, 0x02},
#endif

	{0x90, SEQUENCE_END, 0x00}
};
#endif // DES_CFG

#if defined (SER_CFG)
struct reginfo max96717_rgb888_gmsl2[] =
{
//	{0x80, 0x0001, 0x08},// default 0x08, 6Gbps mode
//	{0x80, 0x0001, 0x14},// 3Gbps mode
//	{0x80, 0x0010, 0x21},// reset link and registers

	{0x80, SEQUENCE_WAIT_MS, 0x80},
	{0x80, 0x0331, 0x30},//default 0x30, 4lane
//	{0x80, 0x0318, 0x5E},//mem_dt1_selz
	{0x80, 0x0318, 0x64},//mem_dt1_selz

	{0x80, SEQUENCE_END, 0x00}
};

struct reginfo max9295_yuv422_gmsl1[] =
{
// GMSL1 for MAX9295, YUV422
//  {0x80, 0x0010, 0x21},   // Link A is selected
//  {0x80, SEQUENCE_WAIT_MS, 0x80},
//  {0x80, 0x0001, 0x14},   // 14=Remote control channel disabled, 3Gbs;  default 08=Remote control channel Enabled, 6Gbs,
//  {0x80, 0x0001, 0x04},   // 3Gbs with Remote control;
	{0x80, 0x0404, 0x40},   // Enable configuration link. Disable serialization, reverse-control channel, forward-control channel transmitte
	{0x80, 0x0402, 0x20},   // Spread spectrum enabled
	{0x80, 0x0002, 0x03},   // undocumented, SRNG 2%
//	{0x80, 0x0407, 0x20},   // Disable HIBW, Set bus width for 30-bit bus (32-bit mode); Disable HS/VS encoding ...
	{0x80, 0x0407, 0x84},   // DBL:Use double-rate output (2x word rate at 1/2x width), Enable HS/VS encoding
	{0x80, 0x044D, 0x80},   // Reverse-channel high-immunity mode (HIM) enabled
	{0x80, 0x0415, 0x02},   // VESA mapping, none rgb888 bit mapping
	{0x80, 0x0308, 0x7D},   // Line-start information frames enabled;  CSI on Port B enabled;  CSI on Port A enabled; CSI port B selection for Video Pipeline U/Z/X; CSI port A selection for Video Pipeline Y
	{0x80, 0x0002, 0xF3},   // Video transmit Channel U/Z/Y/X enabled
	{0x80, 0x0404, 0xC0},   // Enable serialization and configuration link; Disable serialization, reverse-control channel, forward-control channel transmitte
	{0x80, SEQUENCE_END, 0x00}
#if 0
// Max96722 ref config
	{0x90, 0x0013, 0x40},   // Device Reset
	{0x90, SEQUENCE_WAIT_MS, 0x80},
	{0x90, 0x0017, 0x14},   // Enable wake-up by remote chip connected to Link A
	{0x90, 0x0019, 0x94},   // Regulator bleeder current off, REG_MNL: When VDD = 1.2V, enable VDD LDO regulator by first setting REG_ENABLE = 1 and then setting REG_MNL = 1
	{0x90, 0x040B, 0x00},   // CSI output disabled
	{0x90, 0x0B06, 0xEF},   // Reverse channel high immunity mode (HIM) enabled, Link A
	{0x90, 0x0C06, 0xEF},   // Reverse channel high immunity mode (HIM) enabled, Link B
	{0x90, 0x0D06, 0xEF},   // Reverse channel high immunity mode (HIM) enabled, Link C
	{0x90, 0x0E06, 0xEF},   // Reverse channel high immunity mode (HIM) enabled, Link D
	{0x90, 0x0B0F, 0x01},   // MAX9272 style PRBS test, Disable processing HS and DE signals, Link A
	{0x90, 0x0C0F, 0x01},   // MAX9272 style PRBS test, Disable processing HS and DE signals, Link B
	{0x90, 0x0D0F, 0x01},   // MAX9272 style PRBS test, Disable processing HS and DE signals, Link C
	{0x90, 0x0E0F, 0x01},   // MAX9272 style PRBS test, Disable processing HS and DE signals, Link D
	{0x90, 0x0022, 0xFF},   // Coax drive, Link A+B+C+D
	{0x90, 0x0B04, 0x03},   // Enable forward control channel transmitter, Link A
	{0x90, 0x0C04, 0x03},   // Enable forward control channel transmitter, Link B
	{0x90, 0x0D04, 0x03},   // Enable forward control channel transmitter, Link C
	{0x90, 0x0E04, 0x03},   // Enable forward control channel transmitter, Link D
	{0x90, 0x0B07, 0x84},   // DBL:Use double-rate output (2x word rate at 1/2x width), Enable HS/VS encoding
	{0x90, 0x0C07, 0x84},   //
	{0x90, 0x0D07, 0x84},   //
	{0x90, 0x0E07, 0x84},   //
	{0x90, 0x041A, 0xF0},   // Pipe 0123 Enable YUV422 8-bit and 10-bit mux
	{0x90, 0x08A0, 0x04},   // MIPI PHY 2x4 mode
	{0x90, 0x08A2, 0x34},   // Enable MIPI PHY0/PHY1
	{0x90, 0x00F4, 0x0F},   // Enable Pipe 0123
	{0x90, 0x094A, 0xC0},   // Four data lanes tx port1
	{0x90, 0x08A3, 0xE4},   // Map D1 to data lane D3 ...
	{0x90, 0x040C, 0x00},   // none VC software-override
	{0x90, 0x040D, 0x00},   //
	{0x90, 0x040E, 0x5E},   // DT software-override 1E(yuv422-8bit)
	{0x90, 0x040F, 0x7E},   //
	{0x90, 0x0410, 0x7A},   //
	{0x90, 0x0411, 0x48},   // BPP software-override
	{0x90, 0x0412, 0x20},   //
	{0x90, 0x0415, 0xEA},   // software-override enable, and MIPI PHY0 DPLL frequency 1000Mbps
	{0x90, 0x0418, 0xEA},   // software-override enable, and MIPI PHY0 DPLL frequency 1000Mbps

	{0x90, 0x090B, 0x07},   // Mapping enable Map SRC_x to DES_x
	{0x90, 0x092D, 0x15},   // Mapping destination controller
	{0x90, 0x090D, 0x1E},   // Video Pipe Source Mapping, DT
	{0x90, 0x090E, 0x1E},   // Video Pipe Destination Mapping Register, DT
	{0x90, 0x090F, 0x00},   // Video Pipe Source Mapping, FS
	{0x90, 0x0910, 0x00},   // Video Pipe Destination Mapping Register, FS
	{0x90, 0x0911, 0x01},   // Video Pipe Source Mapping, FE
	{0x90, 0x0912, 0x01},   // Video Pipe Destination Mapping Register, FE

	{0x90, 0x094B, 0x07},   //
	{0x90, 0x096D, 0x15},   //
	{0x90, 0x094D, 0x1E},   //
	{0x90, 0x094E, 0x5E},   //
	{0x90, 0x094F, 0x00},   //
	{0x90, 0x0950, 0x40},   //
	{0x90, 0x0951, 0x01},   //
	{0x90, 0x0952, 0x41},   //

	{0x90, 0x098B, 0x07},   //
	{0x90, 0x09AD, 0x15},   //
	{0x90, 0x098D, 0x1E},   //
	{0x90, 0x098E, 0x9E},   //
	{0x90, 0x098F, 0x00},   //
	{0x90, 0x0990, 0x80},   //
	{0x90, 0x0991, 0x01},   //
	{0x90, 0x0992, 0x81},   //

	{0x90, 0x09CB, 0x07},   //
	{0x90, 0x09ED, 0x15},   //
	{0x90, 0x09CD, 0x1E},   //
	{0x90, 0x09CE, 0xDE},   //
	{0x90, 0x09CF, 0x00},   //
	{0x90, 0x09D0, 0xC0},   //
	{0x90, 0x09D1, 0x01},   //
	{0x90, 0x09D2, 0xC1},   //

	{0x90, 0x04A2, 0x00},   // Master link select for frame sync generation, K_VAL
	{0x90, 0x04AA, 0x00},   // Low byte of the overlap window value
	{0x90, 0x04AB, 0x00},   // High bits of the overlap window value
	{0x90, 0x04AF, 0x40},   // Do not include VideoPipe 0123 in frame sync generation, Uses crystal oscillator clock for generating frame sync signal
	{0x90, 0x04A7, 0x0F},   // High byte of frame sync period
	{0x90, 0x04A6, 0x42},   // Middle byte of frame sync period
	{0x90, 0x04A5, 0x40},   // Low byte of frame sync period
	{0x90, 0x04A0, 0x04},   // Frame Synchronization Method Manual, Frame sync generation is on. GPIO is used as FSYNC output and drives a slave device
	{0x90, 0x04B1, 0x00},   // GPIO ID used for transmitting FSYNC signal
	{0x90, 0x0B08, 0x10},   // Enables frame sync signal transmission, Link A
	{0x90, 0x0C08, 0x10},   // Enables frame sync signal transmission, Link B
	{0x90, 0x0D08, 0x10},   // Enables frame sync signal transmission, Link C
	{0x90, 0x0E08, 0x10},   // Enables frame sync signal transmission, Link D
	{0x90, 0x0018, 0x0F},   // Link A/B/C/D One-Shot Reset
	{0x90, SEQUENCE_WAIT_MS, 0x80},
	{0x90, 0x0006, 0x0F},   // Enable link A/B/C/D
	{0x90, SEQUENCE_WAIT_MS, 0x0A},
	{0x90, 0x08A2, 0x00},   // MIPI PHY Disable
	{0x90, SEQUENCE_WAIT_MS, 0x01},
	{0x90, 0x08A2, 0xF4},   // MIPI PHY Enable
	{0x90, 0x08A0, 0x84},   // Force all MIPI clocks running
	{0x90, SEQUENCE_WAIT_MS, 0x01},
	{0x90, 0x040B, 0x42},   // Enables MIPI CSI output
	{0x90, SEQUENCE_END, 0x00},
#endif
};
#endif // SER_CFG

int max929x_write(i2c_no i2c, u8 addr, u16 reg, u8 data)
{
	int ret;
	ret = xgpio_i2c_reg16_write(i2c, addr>>1, reg, data, STRETCH_ON);
	return ret;
}

void max929x_write_array(i2c_no i2c, struct reginfo *regarray)
{
	int i = 0;

	while (regarray[i].reg != SEQUENCE_END)
	{
		if(regarray[i].reg == SEQUENCE_WAIT_MS)
		{
		      usleep((regarray[i].val)*1000);
		}
		else
		{
			max929x_write(i2c, regarray[i].addr, regarray[i].reg,regarray[i].val);
		}
		i++;
	}
}

#endif // SER_CFG || DES_CFG
#endif // #if defined(XPAR_XGPIO_I2C_0_AXI_GPIO_0_DEVICE_ID)

/*
usage:
assume you have a xgpio_i2c heir, or you can modify to use xiic or emio_i2c

ref to follows
```
#if defined (SER_CFG) || defined (DES_CFG)
    // MAX9296 config
    u8 ret8=0;
#if defined (DES_CFG)
    Status = xgpio_i2c_reg16_read(I2C_NO_3, 0x90>>1, 0x0000, &ret8, STRETCH_ON);
    Status = xgpio_i2c_reg16_read(I2C_NO_3, 0x90>>1, 0x0001, &ret8, STRETCH_ON);
#if defined (SERDES_3G)
    Status = xgpio_i2c_reg16_write(I2C_NO_3, 0x90>>1, 0x0001, 0x01, STRETCH_ON); // 3Gbps
    Status = xgpio_i2c_reg16_write(I2C_NO_3, 0x90>>1, 0x0010, 0x21, STRETCH_ON); // reset link
#else
    Status = xgpio_i2c_reg16_write(I2C_NO_3, 0x90>>1, 0x0001, 0x02, STRETCH_ON); // 6Gbps
	Status = xgpio_i2c_reg16_write(I2C_NO_3, 0x90>>1, 0x0010, 0x21, STRETCH_ON); // reset link
#endif // SERDES_3G
    max929x_write_array(I2C_NO_3, max9296_rgb888_gmsl2);
#endif // DES_CFG
#if defined (SER_CFG)
    Status = xgpio_i2c_reg16_read(I2C_NO_3, 0x80>>1, 0x0000, &ret8, STRETCH_ON);
    Status = xgpio_i2c_reg16_read(I2C_NO_3, 0x80>>1, 0x0001, &ret8, STRETCH_ON);
#if defined (SERDES_3G)
    Status = xgpio_i2c_reg16_write(I2C_NO_3, 0x80>>1, 0x0001, 0x04, STRETCH_ON); // 3Gbps
    Status = xgpio_i2c_reg16_write(I2C_NO_3, 0x80>>1, 0x0010, 0x21, STRETCH_ON); // reset link
#else
    Status = xgpio_i2c_reg16_write(I2C_NO_3, 0x80>>1, 0x0001, 0x08, STRETCH_ON); // 6Gbps
    Status = xgpio_i2c_reg16_write(I2C_NO_3, 0x80>>1, 0x0010, 0x21, STRETCH_ON); // reset link
#endif // SERDES_3G
//    max929x_write_array(I2C_NO_3, max9295_rgb888_gmsl2);
    max929x_write_array(I2C_NO_3, max96717_rgb888_gmsl2);
#endif // SER_CFG
#if defined (DES_CFG)
    Status = xgpio_i2c_reg16_read(I2C_NO_3, 0x90>>1, 0x0000, &ret8, STRETCH_ON);
	Status = xgpio_i2c_reg16_read(I2C_NO_3, 0x90>>1, 0x0001, &ret8, STRETCH_ON);
#endif // DES_CFG
#if defined (SER_CFG)
    Status = xgpio_i2c_reg16_read(I2C_NO_3, 0x80>>1, 0x0000, &ret8, STRETCH_ON);
    Status = xgpio_i2c_reg16_read(I2C_NO_3, 0x80>>1, 0x0001, &ret8, STRETCH_ON);
#endif // SER_CFG
#endif // SER_CFG || DES_CFG
```
*/
